﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows.Input;
using ExpensesClient.ExpensesServiceReference;
using ExpensesClient.Repositories;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

namespace ExpensesClient.ViewModels
{
    // Note: The project use http://code.google.com/p/notifypropertyweaver/ to generate INotifyPropertyChanged events
    public class MainPageViewModel : ViewModelBase
    {
        public MainPageViewModel()
        {
            CheckForSupportedEvents = new AutoResetEvent(false);
            ExpenseItems = new ObservableCollection<ExpenseItem>();
            ExpenseService = new ExpenseService();

            StartNew = new RelayCommand(OnStartNew);
            AddExpense = new RelayCommand(OnAddExpense);
            Submit = new RelayCommand(OnSubmit);

            DisplayRandomItem();

            if (!IsInDesignMode)
            {
                var cnt = SynchronizationContext.Current;
                var firstTime = true;


                ThreadPool.QueueUserWorkItem(_ =>
                {
                    while (true)
                    {
                        ExpenseService.GetSupprotedBookmarks(bm =>
                        {
                            cnt.Post(s =>
                            {
                                var canStartNew = true;
                                var canAddExpense = bm.IndexOf("[AddExpense|") > -1;
                                var canSubmit = bm.IndexOf("[Submit|") > -1;
                                var canGetExpenses = bm.IndexOf("[GetExpenses|") > -1;

                                if (canAddExpense || canSubmit)
                                {
                                    canStartNew = false;
                                }

                                CanStartNew = canStartNew;
                                CanAddExpense = canAddExpense;
                                CanSubmit = canSubmit;

                                if (firstTime && canGetExpenses)
                                {
                                    firstTime = false;
                                    ExpenseService.GetExpenses(items =>
                                        {
                                            ExpenseItems.Clear();

                                            foreach (var item in items)
                                            {
                                                ExpenseItems.Add(item);
                                            }
                                        });
                                }
                            }, null);
                        });
                        CheckForSupportedEvents.WaitOne(TimeSpan.FromSeconds(15));
                    }
                }, null);
            }
        }

        public ICommand StartNew { get; private set; }
        public ICommand AddExpense { get; private set; }
        public ICommand Submit { get; private set; }
        public ExpenseService ExpenseService { get; private set; }
        public ObservableCollection<ExpenseItem> ExpenseItems { get; private set; }
        public bool CanStartNew { get; private set; }
        public bool CanAddExpense { get; private set; }
        public bool CanSubmit { get; private set; }
        public string ExpenseItemDescription { get; set; }
        public decimal ExpenseItemAmount { get; set; }
        public AutoResetEvent CheckForSupportedEvents { get; set; }

        private void OnStartNew()
        {
            DisableControls();
            ExpenseService.StartNew(() =>
            {
                ExpenseItems.Clear();
                DisplayRandomItem();
                CheckForSupportedEvents.Set();
            });
        }

        private void OnAddExpense()
        {
            DisableControls();
            ExpenseService.AddExpense(ExpenseItemDescription, ExpenseItemAmount, newItems =>
            {
                ExpenseItems.Clear();

                foreach (var item in newItems)
                {
                    ExpenseItems.Add(item);
                }

                DisplayRandomItem();
                CheckForSupportedEvents.Set();
            });
        }

        private void OnSubmit()
        {
            DisableControls();
            ExpenseService.OnSubmit(() =>
            {
                ExpenseItems.Clear();
                CheckForSupportedEvents.Set();
            });
        }

        private void DisplayRandomItem()
        {
            var items = new List<string> { "Dinner", "Airfare", "Rail", "Car hire", "Petrol", "Hotel", "XXX" };
            var random = new Random();
            var index = random.Next(items.Count);

            ExpenseItemDescription = items[index];
            ExpenseItemAmount = random.Next(125);
        }

        private void DisableControls()
        {
            CanStartNew = false;
            CanAddExpense = false;
            CanSubmit = false;
        }
    }
}
